/*
 * File:   Experiment.h
 * Author: jcrada
 *
 * Created on April 20, 2009, 10:56 PM
 */

#ifndef _EXPERIMENT_H
#define	_EXPERIMENT_H
#include "Creature.h"

#include "TreeOfNodes.h"
#include "PsoModel.h"

#include <string>
#include <QtXml/QDomElement>
namespace jcrada {

    class Experiment {
    public:
        std::string _description;
        Creature** _evolved_creatures;
        Creature** _best_creatures;
        TreeOfNodes* _best_creature_morphology;
        TreeOfNodes* _preferred_morphology;
        
        int _record_best_creatures_modulo;
        int _body_parts;
        int _current_iteration;
        int _hidden_layers;
        int _iterations;
        double _max_mass;
        double _max_size;
        double _min_mass;
        double _min_size;
        int _morphologies;
        int _neurons_per_layer;
        int _population_size;
        int _time_in_seconds;

        double* _fitness_in_time;
        double* _creature_fitness;
        int* _morphology_index;
        BodyPart::eShape* _root_shape;
        int* _shape_capsules;
        int* _shape_cones;
        int* _shape_cylinders;
        int* _shape_parallelepipeds;
        int* _shape_spheres;

        double* _creature_mass;
        double* _root_mass;
        double* _non_root_mass_mean;

        double* _creature_volume;
        double* _root_volume;
        double* _non_root_volume_mean;

        int* _swing_x_blocked;
        int* _swing_x_medium;
        int* _swing_x_free;
        int* _twist_y_blocked;
        int* _twist_y_medium;
        int* _twist_y_free;
        int* _swing_z_blocked;
        int* _swing_z_medium;
        int* _swing_z_free;

        double** _swing_x;
        double** _twist_y;
        double** _swing_z;

        PsoModel* _pso;

    protected:
        void countShape(int creature_index, BodyPart::eShape shape);
        void countConstraintLimits(int creature_index, double swing_x, double twist_y, double swing_z);
        void loadConstraintLimits(int creature_index, const Creature& creature);
        static void statsFromXml(Experiment& exp, QDomElement& xml, bool* ok);
        static void fitnessOverTimeFromXml(Experiment& exp, QDomElement& xml, bool* ok);
    public:
        Experiment(const std::string& description, int iterations, 
                int population_size, int body_parts,
                int record_best_creatures_modulo = 5);
        virtual ~Experiment();

        virtual void analyze();

        QDomElement headerToXml(QDomDocument& xml) const;
        void statisticsToXml(QDomDocument& xml, QDomElement * parent = NULL) const;
        void bestCreaturesToXml(QDomDocument& xml, QDomElement * parent = NULL) const;
        void evolvedCreaturesToXml(QDomDocument& xml, QDomElement * parent = NULL) const;
        void particlesToXml(QDomDocument& xml, QDomElement * parent = NULL) const;

        static Experiment* fromXml(QDomElement& xml, bool* ok);

        static int main(int argc, char** argv);
    };
}

#endif	/* _EXPERIMENT_H */
